import json
import os
import platform
import re
import signal
import time
from pathlib import Path
from urllib.parse import urljoin
from urllib.parse import urlparse

import requests


def check_result_dir():
    #
    my_dir = os.path.dirname(__file__)
    workdir_name = 'result'
    workdir = my_dir + os.sep + workdir_name
    os.chdir(my_dir)
    if not Path(workdir).is_dir():
        os.mkdir(workdir_name)


def _handle_timeout(signum, frame):
    raise TimeoutError('下载超时：%s %s' % (signum, frame))


def speedtest(url):
    """
    下载测速(速度单位KiB/s)

    :param url: 要测速的url
    :type url: str
    """
    timeout_sec = 10
    signal.signal(signal.SIGALRM, _handle_timeout)
    signal.alarm(timeout_sec)
    try:
        start_time = int(round(time.time() * 1000))

        result = requests.get(url, timeout=5, allow_redirects=False)

        if result.status_code == 200:

            end_time = int(round(time.time() * 1000))
            use_time = (end_time - start_time) / 1000
            size = result.headers.get('Content-Length')
            if size is None:
                size = len(result.content)
            size = int(size)
            # 速度单位：KiB/s
            speed = int(round((size / 1024) / use_time))
            print("链接：%s\n大小：%s KiB 用时：%s s 速度：%s KiB/s" % (url, int(round(size / 1024)), use_time, speed))
            return size, use_time, speed
    except Exception as errors:
        print("测速错误:\n%s" % errors)
        return 0, 0, 0
    finally:
        signal.alarm(0)
    return 0, 0, 0


def check_speed(m3u8_url, m3u8_content=None):
    """
    m3u8地址速度测试
    :param m3u8_url: 测试的m3u8的url
    :param m3u8_content: url的内容
    :type m3u8_url: basestring
    :type m3u8_content: basestring
    """
    print("测试链接：%s" % m3u8_url)
    # 获取m3u8内容
    if m3u8_content is None:
        try:
            content_result = requests.get(m3u8_url, timeout=5)
            if content_result.status_code == 200:
                m3u8_content = content_result.text
            else:
                raise ConnectionError("错误码：%s" % content_result.status_code)
        except Exception as error:
            print("m3u8内容获取错误:\n%s" % error)
            return 0, 0, 0
    # 获取、合成测速url
    url_pattern = r'^[^#\s].*'
    # 匹配完整url
    isurl_pattern = re.compile(r'^(http|https)://.*')

    result_url = re.findall(url_pattern, m3u8_content, re.M)[0]
    isurl = re.match(isurl_pattern, result_url)

    if isurl is None:
        target_url = urljoin(m3u8_url, result_url).strip()
    else:
        target_url = result_url
    # 完整url
    # 匹配是否是m3u8 url
    m3u8_pattern = r'.*(\.m3u8)$'
    ism3u8 = re.match(m3u8_pattern, urlparse(target_url).path)
    if ism3u8 is not None:
        return check_speed(target_url)

    return speedtest(target_url)


def save_result(file_name: str, data):
    file_path = 'result' + os.sep + file_name
    with open(file_path, 'w+', encoding="utf-8") as file:
        for item in data:
            file.write(item)

    print(file_path + '写入完成')


def save_json(filename, data):
    file_name = 'result' + os.sep + filename
    with open(file_name, 'w', encoding='utf-8') as file:
        file.write(json.dumps(data, ensure_ascii=False))
    print(file_name + '写入完成')


def merge_get_json_list(filepath):
    with open(filepath, 'r', encoding='utf-8') as json_file:
        return json.loads(json_file.read())


def merge_json_list(workdir):
    filenames = os.listdir(workdir)
    data = []
    for filename in filenames:
        if filename.endswith('.json'):
            filepath = workdir + os.sep + filename
            file_content = merge_get_json_list(filepath)
            data.extend(file_content)
    return data


def merge_sort_key(s):
    num_pattern = re.compile(r'(\d+)')
    p = num_pattern.split(s['tag_name'])
    p[1::2] = map(int, p[1::2])
    return p


def merge_sort_json_list(json_list):
    """

    :param json_list:dict or list
    :return: dict or list
    """
    json_list.sort(key=merge_sort_key)
    return json_list


def merge_from_json_output_m3u(result_json, output):
    with open(output, 'w', encoding='utf-8') as file:
        for item in result_json:
            file.write(build_m3u_data(item['logo'], item['category'], item['channel_name'], item['play_url']))


def merge():
    workdir_name = 'result'
    my_dir = os.path.dirname(__file__)
    workdir = my_dir + os.sep + workdir_name

    if platform.system() == 'Linux':
        if os.path.exists('/var/www/html/'):
            output = '/var/www/html/' + 'allinone.m3u'
        elif os.path.exists('/www'):
            output = '/www' + os.sep + 'allinone.m3u'
        else:
            output = my_dir + os.sep + 'allinone.m3u'
    else:
        output = my_dir + os.sep + 'allinone.m3u'
    # json_output = my_dir + os.sep + 'allinone' + '.json'

    restlt_json = merge_sort_json_list(merge_json_list(workdir))
    merge_from_json_output_m3u(restlt_json, output)
    print('文件合并完毕')


def schedule_process(filename, data):
    check_result_dir()
    save_json(filename, data)
    merge()


def build_m3u_data(logo: str, category: str, channel_name: str, play_url: str):
    """
    :rtype: str
    """
    channel_data = '#EXTINF:-1, tvg-logo="{}", group-title="{}", {}\n{}\n'.format(logo, category, channel_name,
                                                                                  play_url)
    return channel_data


def build_m3u_json(logo: str, category: str, channel_name: str, play_url: str):
    """
    :rtype: json
    """
    # 匹配cctv
    num_pattern = re.compile(r'[A-Za-z]+\d+')
    num_match = re.match(pattern=num_pattern, string=channel_name)
    if num_match is not None:
        tag_name = num_match[0]
    else:
        tag_name = channel_name.replace('高清', '').strip()
    # print(tag_name)
    json_data = {
        'tag_name': tag_name,
        'logo': logo,
        'category': category,
        'channel_name': channel_name,
        'play_url': play_url,
    }

    # return json.dumps(json_data, ensure_ascii=False)
    return json_data
